package turritopsis

import (
    "bufio"
    "encoding/json"
    "fmt"
    "log"
    "net"
    "sync"
    "time"
    "adkr/pkg/adkr"
)

// Minimal TCP router: JSON line per message; suitable for demos/AWS. Not production-hardened.
type TCPRouter struct {
    addr string
    isServer bool
    ln net.Listener
    conn net.Conn
    mu sync.Mutex
    // one pair for all epochs (simplified); a real impl can shard per-epoch
    in  chan adkr.Message
    out chan adkr.Message
}

func NewTCPRouter(addr string, server bool) *TCPRouter {
    return &TCPRouter{addr: addr, isServer: server, in: make(chan adkr.Message, 1024), out: make(chan adkr.Message, 1024)}
}

func (r *TCPRouter) Start() error {
    if r.isServer {
        ln, err := net.Listen("tcp", r.addr)
        if err != nil { return err }
        r.ln = ln
        go func() {
            for {
                c, err := ln.Accept()
                if err != nil { log.Printf("tcp accept err: %v", err); continue }
                r.mu.Lock(); r.conn = c; r.mu.Unlock()
                go r.handleConn(c)
            }
        }()
        go r.writerLoop()
        return nil
    }
    // client
    var d net.Dialer
    c, err := d.Dial("tcp", r.addr)
    if err != nil { return err }
    r.conn = c
    go r.handleConn(c)
    go r.writerLoop()
    return nil
}

func (r *TCPRouter) handleConn(c net.Conn) {
    rd := bufio.NewReader(c)
    dec := json.NewDecoder(rd)
    for {
        var m adkr.Message
        if err := dec.Decode(&m); err != nil { log.Printf("tcp read err: %v", err); return }
        r.in <- m
    }
}

func (r *TCPRouter) writerLoop() {
    for m := range r.out {
        r.mu.Lock(); c := r.conn; r.mu.Unlock()
        if c == nil { time.Sleep(10*time.Millisecond); continue }
        bw := bufio.NewWriter(c)
        enc := json.NewEncoder(bw)
        if err := enc.Encode(m); err != nil { log.Printf("tcp write err: %v", err) }
        if err := bw.Flush(); err != nil { log.Printf("tcp flush err: %v", err) }
    }
}

func (r *TCPRouter) KRChannels(epoch int) (<-chan adkr.Message, chan<- adkr.Message) {
    return r.in, r.out
}

func (r *TCPRouter) ACSChannels(epoch int) (<-chan adkr.Message, chan<- adkr.Message) {
    return nil, nil
}

func (r *TCPRouter) Close() error {
    if r.ln != nil { _ = r.ln.Close() }
    if r.conn != nil { _ = r.conn.Close() }
    close(r.out)
    return nil
}

func (r *TCPRouter) String() string { return fmt.Sprintf("TCPRouter(%s, server=%v)", r.addr, r.isServer) }




